#include "memory.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>

typedef struct _FIFOBUFFER
{
    uint8_t *pBuffer, *pRead, *pWrite, *pEnd;
}FIFOBUFFER, *PFIFOBUFFER;

//semaphore
SEMAPHOREHANDLE SemaphoreCreate()
{
    sem_t *hHandle = (sem_t *)malloc(sizeof(sem_t));
    if(NULL == hHandle)
    {
        return NULL;
    }
    if(0 != sem_init(hHandle, 0, 1))    //线程间同步
    {
        free(hHandle);
        hHandle = NULL;
        return NULL;
    }
     return (SEMAPHOREHANDLE)hHandle;
}

int SemaphoreDestroy(SEMAPHOREHANDLE hSemaphoreHandle)
{
    sem_t *hHandle = (sem_t *)hSemaphoreHandle;
    if(NULL != hHandle)
    {
        if(0 != sem_destroy(hHandle))
        {
            return 0;
        }
        if(NULL != hHandle)
        {
            free(hHandle);
            hHandle = 0;
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

//获取信号量
int SemaphoreTake(SEMAPHOREHANDLE hSemaphoreHandle)
{
    uint32_t u32Return = 0;
    sem_t *hHandle = (sem_t *)hSemaphoreHandle;
    if(NULL != hHandle)
    {
        u32Return = sem_wait(hHandle);
        if(0 != u32Return)
        {
            return 0;
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

//释放信号量
int SemaphoreGive(SEMAPHOREHANDLE hSemaphoreHandle)
{
    sem_t *hHandle = (sem_t *)hSemaphoreHandle;
    if(NULL != hHandle)
    {
        if(0 != sem_post(hHandle))
        {
            return 0;
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

FIFOBUFFERHANDLE FifoBufferCreate(int s32Size)
{
    PFIFOBUFFER ptFifoBuffer = NULL;
    do
    {
        ptFifoBuffer = (PFIFOBUFFER)malloc(sizeof(FIFOBUFFER));
        if(NULL == ptFifoBuffer)
        {
            break;
        }
        memset(ptFifoBuffer, 0, sizeof(FIFOBUFFER));
        ptFifoBuffer->pBuffer = (uint8_t *)malloc(s32Size);
        if(NULL == ptFifoBuffer->pBuffer)
        {
            break;
        }
        memset(ptFifoBuffer->pBuffer, 0, s32Size);
        ptFifoBuffer->pWrite = ptFifoBuffer->pRead = ptFifoBuffer->pBuffer;
        ptFifoBuffer->pEnd = ptFifoBuffer->pBuffer + s32Size;
        return (FIFOBUFFERHANDLE)ptFifoBuffer;
    }while(false);
    if(NULL != ptFifoBuffer)
    {
        if(NULL != ptFifoBuffer->pBuffer)
        {
            free(ptFifoBuffer->pBuffer);
            ptFifoBuffer->pBuffer = NULL;
        }
        free(ptFifoBuffer);
        ptFifoBuffer = NULL;
    }
    return NULL;
}

void FifoBufferDestroy(FIFOBUFFERHANDLE pHandle)
{
    PFIFOBUFFER ptFifoBuffer = (PFIFOBUFFER)pHandle;
    if(NULL != ptFifoBuffer)
    {
        if(NULL != ptFifoBuffer->pBuffer)
        {
            free(ptFifoBuffer->pBuffer);
            ptFifoBuffer->pBuffer = NULL;
        }
        free(ptFifoBuffer);
        ptFifoBuffer = NULL;
    }
}

void FifoBufferReset(FIFOBUFFERHANDLE pHandle)
{
    PFIFOBUFFER ptFifoBuffer = (PFIFOBUFFER)pHandle;
    if(NULL != ptFifoBuffer)
    {
        ptFifoBuffer->pWrite = ptFifoBuffer->pRead = ptFifoBuffer->pBuffer;
    }
}

/**
 * 返回内存池中有效数据的长度
 */
int FifoBufferSize(FIFOBUFFERHANDLE pHandle)
{
    int s32Size = 0;
    PFIFOBUFFER ptFifoBuffer = (PFIFOBUFFER)pHandle;
    if(NULL != ptFifoBuffer)
    {
        s32Size = ptFifoBuffer->pWrite - ptFifoBuffer->pRead;
        if(s32Size < 0) //pWrite已被重新初始化为pBuffer，从头写数据了
        {
            s32Size += ptFifoBuffer->pEnd - ptFifoBuffer->pBuffer;
        }
    }
    return s32Size;
}

/**
  * 内存空间在创建的时候由用户决定其大小
  * 在向其写入数据时，如果pWrite地址超过pEnd溢出时，pWrite将重新初始化为pBuffer,即头部，将剩余的数据写入
  * 如果申请的内存过小时，可能会造成数据的重叠，导致数据的损失
  */
int FifoBufferWrite(FIFOBUFFERHANDLE pHandle, uint8_t *pBuffer, int s32Size)
{
    int s32Length = 0;
    PFIFOBUFFER ptFifoBuffer = (PFIFOBUFFER)pHandle;
    if(NULL == ptFifoBuffer)
    {
        return 0;
    }
    do
    {
        /**
         * 1、内存空间足够，全部copy到内存中
         * 2、内存空间已经没有足够s32size大小的空间了
         */
        s32Length = _min(ptFifoBuffer->pEnd - ptFifoBuffer->pWrite, s32Size);
        memcpy(ptFifoBuffer->pWrite, pBuffer, s32Length);
        pBuffer = pBuffer + s32Length;
        ptFifoBuffer->pWrite += s32Length;
        if(ptFifoBuffer->pWrite >= ptFifoBuffer->pEnd)
        {
            ptFifoBuffer->pWrite = ptFifoBuffer->pBuffer;
        }
        s32Size -= s32Length;
    }while(s32Size > 0);
    return 1;
}

int FifoBufferRead(FIFOBUFFERHANDLE pHandle, uint8_t *pBuffer, int *ps32Size)
{
    int s32Length = 0, pTempSize = (*ps32Size);
    PFIFOBUFFER ptFifoBuffer = (PFIFOBUFFER)pHandle;
    if(NULL == ptFifoBuffer || NULL == pBuffer || 0 > pTempSize)
    {
        return 0;
    }
    if(0 == pTempSize)
    {
        (*ps32Size) = 0;
        return 1;
    }
    (*ps32Size) = 0;
    do
    {
        s32Length = _min(FifoBufferSize(pHandle), pTempSize);
        s32Length = _min(ptFifoBuffer->pEnd - ptFifoBuffer->pRead, s32Length);
        if(0 == s32Length)
        {
            break;
        }
        memcpy(pBuffer, ptFifoBuffer->pRead, s32Length);
        pBuffer += s32Length;
        ptFifoBuffer->pRead += s32Length;
        if(ptFifoBuffer->pRead >= ptFifoBuffer->pEnd)
        {
            ptFifoBuffer->pRead = ptFifoBuffer->pBuffer;
        }
        pTempSize -= s32Length;
        (*ps32Size) += s32Length;
    }while(pTempSize > 0);
    return 1;
}

typedef struct _TTHREAD
{
    pthread_t hThreadHandle;
    void *pvEntry;          //线程函数入口
    void *pvArglist;        //线程函数参数
    int s32Delay, s32Quit;  //s32Delay线程延迟时间，单位为微妙；s32Quit标识线程是否退出
}TTHREAD, *PTTHREAD;

void *ThreadEntry(void *pvVoid)
{
    PTTHREAD ptThread = (PTTHREAD)pvVoid;
    do
    {
        if(1 == ptThread->s32Quit)
        {
            break;
        }
        else
        {
            if(NULL != ptThread->pvEntry)
            {
                ((THREADENTRY)ptThread->pvEntry)(ptThread->pvArglist);
            }
            if(0 < ptThread->s32Delay)
            {
                ThreadDelay(ptThread->s32Delay);
            }
        }
    }while(1);
    int s32Value = 0;
    pthread_detach(pthread_self());
    pthread_exit(&s32Value);
}

THREADHANDLE ThreadCreate(void *pvEntry, void *pvArglist, int s32Delay)
{
    PTTHREAD ptThread = (PTTHREAD)malloc(sizeof(TTHREAD));
    if(NULL == ptThread)
    {
        return NULL;
    }
    memset(ptThread, 0, sizeof(TTHREAD));
    ptThread->pvEntry = pvEntry;
    ptThread->pvArglist = pvArglist;
    ptThread->s32Delay = s32Delay;
    ptThread->s32Quit = 0;
    int s32Value = 0;
    s32Value = pthread_create(&ptThread->hThreadHandle, NULL, ThreadEntry, ptThread);
    if(0 != s32Value)
    {
        return NULL;
    }
    return (THREADHANDLE)ptThread;
}

int ThreadWaitEnd(THREADHANDLE hThreadHandle)
{
    PTTHREAD ptThread = (PTTHREAD)hThreadHandle;
    if(NULL != ptThread)
    {
        ptThread->s32Quit = 1;
        void *pvReturnValue = NULL;
        if(0 != pthread_join(ptThread->hThreadHandle, &pvReturnValue))
        {
            return 0;
        }
        free(ptThread);
        ptThread = NULL;
    }
    return 1;
}

void ThreadDelay(uint32_t u32MSeconds)
{
    struct timeval timeOut = {0, u32MSeconds * 1000 };
    select(0, NULL, NULL, NULL, &timeOut);
}


